package cs.android.rpc;

import static cs.android.lang.AndroidLang.event;
import static cs.java.lang.Lang.createTraceString;
import static cs.java.lang.Lang.doLater;
import static cs.java.lang.Lang.error;
import static cs.java.lang.Lang.fire;

import cs.android.lang.AndroidLang;
import cs.android.lang.ServerRequest;
import cs.android.viewbase.ContextPresenter;
import cs.java.event.Event;
import cs.java.event.Task;
import cs.java.lang.Run;

public abstract class ServerRequestBase extends ContextPresenter implements ServerRequest, Run {

	protected final Event<ServerRequest> onDone = event();
	protected final Event<ServerRequest> onFailed = event();
	protected final Event<ServerRequest> onLoaded = event();
	protected final Event<ServerRequest> onSuccess = event();
	protected String exceptionMessage;
	protected String exceptionDetails;
	protected int messageId;
	protected boolean isDone;
	protected boolean isLoaded;
	protected boolean isSuccess;
	private boolean isStop;

	public ServerRequestBase() {
		doLater(new Run() {
			public void run() {
				if (!isStop) onSend();
			}
		});
	}

	protected final void onDone() {
		doLater(new Run() {
			public void run() {
				isDone = true;
				fire(onDone, ServerRequestBase.this);
			}
		});
	}

	protected void onFailed() {
		fire(onFailed, this);
	}

	protected final void onFailed(final Exception e) {
		doLater(new Run() {
			public void run() {
				error(e);
				AndroidLang.getAplication().logException(e);
				exceptionMessage = e.getMessage();
				exceptionDetails = createTraceString(e);
				onFailed();
			}
		});
	}

	protected final void onFailed(final String message, final String details) {
		doLater(new Run() {
			public void run() {
				error(message, details);
				exceptionMessage = message;
				exceptionDetails = details;
				onFailed();
			}
		});
	}

	protected void onLoaded() {
		if (isSuccess) onSuccess();
		fire(onLoaded, this);
	}

	protected final void onLoaded(final boolean success) {
		doLater(new Run() {
			public void run() {
				isSuccess = success;
				isLoaded = true;
				onLoaded();
			}
		});
	}

	protected void onLoaded(boolean success, final int message) {
		doLater(new Run() {
			public void run() {
				messageId = message;
			}
		});
		onLoaded(success);
	}

	protected void onSend() {
		if (isNetworkConnected()) AndroidLang.getAplication().getRequestManager().send(this);
		else {
			exceptionMessage = "NoInternetConnection";
			onFailed();
			onDone();
		}
	}

	protected void onSuccess() {
		fire(onSuccess, this);
	}

	protected void registerDone(final ServerRequest request) {
		new Task(request.getOnDone()) {
			public void run() {
				ServerRequestBase.this.onDone();
			}
		};
	}

	protected void registerFailed(final ServerRequest request) {
		new Task(request.getOnFailed()) {
			public void run() {
				ServerRequestBase.this.onFailed(request.getExceptionMessage(),
						request.getExceptionDetails());
			}
		};
	}

	@Override public String getExceptionDetails() {
		return exceptionDetails;
	}

	@Override public String getExceptionMessage() {
		return exceptionMessage;
	}

	@Override public int getMessageId() {
		return messageId;
	}

	public Event<ServerRequest> getOnDone() {
		return onDone;
	}

	public Event<ServerRequest> getOnFailed() {
		return onFailed;
	}

	public Event<ServerRequest> getOnLoaded() {
		return onLoaded;
	}

	public Event<ServerRequest> getOnSuccess() {
		return onSuccess;
	}

	@Override public boolean isDone() {
		return isDone;
	}

	@Override public boolean isLoaded() {
		return isLoaded;
	}

	@Override public boolean isSuccess() {
		return isSuccess;
	}

	public void stop() {
		isStop = true;
	}

}
